package bookTrading.buyer;

import jade.core.AID;
import jade.core.Agent;
import jade.core.behaviours.Behaviour;
import jade.core.behaviours.TickerBehaviour;
import jade.domain.DFService;
import jade.domain.FIPAException;
import jade.domain.FIPAAgentManagement.DFAgentDescription;
import jade.domain.FIPAAgentManagement.ServiceDescription;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;

public class BookBuyerAgent extends Agent {

	private class RequestPerformer extends Behaviour {

		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;
		
		private AID bestSeller;
		private int bestPrice;
		private int repliesCnt = 0;
		private MessageTemplate mt;
		private int step = 0;

		@Override
		public void action() {
			switch (step) {
			case 0:
				ACLMessage cfp = new ACLMessage(ACLMessage.CFP);
				for (int i = 0; i < sellerAgents.length; ++i)
					cfp.addReceiver(sellerAgents[i]);
				cfp.setContent(targetBookTitle);
				cfp.setConversationId("book-trade");
				cfp.setReplyWith("cfp" + System.currentTimeMillis());
				myAgent.send(cfp);
				mt = MessageTemplate.and(MessageTemplate.MatchConversationId("book-trade"), MessageTemplate.MatchInReplyTo(cfp.getReplyWith()));
				step = 1;
				break;
			case 1:
				ACLMessage reply = myAgent.receive(mt);
				if (reply != null) {
					if (reply.getPerformative() == ACLMessage.PROPOSE) {
						int price = Integer.parseInt(reply.getContent());
						if (bestSeller == null || price < bestPrice) {
							bestPrice = price;
							bestSeller = reply.getSender();
						}
					}
					repliesCnt++;
					if (repliesCnt >= sellerAgents.length)
						step = 2;
				}
				else
					block();
				break;
			case 2:
				ACLMessage order = new ACLMessage(ACLMessage.ACCEPT_PROPOSAL);
				order.addReceiver(bestSeller);
				order.setContent(targetBookTitle);
				order.setConversationId("book-trade");
				order.setReplyWith("order" + System.currentTimeMillis());
				myAgent.send(order);
				mt = MessageTemplate.and(MessageTemplate.MatchConversationId("book-trade"), MessageTemplate.MatchInReplyTo(order.getReplyWith()));
				step = 3;
				break;
			case 3:
				reply = myAgent.receive(mt);
				if (reply != null) {
					if (reply.getPerformative() == ACLMessage.INFORM) {
						System.out.println(targetBookTitle + " successfully purchased from agent " + reply.getSender().getName());
						System.out.println("Price = " + bestPrice);
						myAgent.doDelete();
					}
					else
						System.out.println("Attempt failed: requested book already sold.");
					step = 4;
				}
				else
					block();
				break;
			}
		}

		@Override
		public boolean done() {
			// TODO Auto-generated method stub
			return false;
		}

	}

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	private String targetBookTitle;
	private AID[] sellerAgents;
	
	@Override
	protected void setup() {
		System.out.println("Hello! Buyer-agent " + getAID().getName() + " is ready.");
		
		Object[] args = getArguments();
		if (args != null && args.length > 0) {
			targetBookTitle = (String) args[0];
			System.out.println("Target book is " + targetBookTitle);
			
			addBehaviour(new TickerBehaviour(this, 60000) {

				/**
				 * 
				 */
				private static final long serialVersionUID = 1L;

				@Override
				protected void onTick() {
					System.out.println("Trying to buy " + targetBookTitle);
					DFAgentDescription template = new DFAgentDescription();
					ServiceDescription sd = new ServiceDescription();
					sd.setType("book-selling");
					template.addServices(sd);
					try {
						DFAgentDescription[] result = DFService.search(myAgent, template);
						System.out.println("Found the following seller agents:");
						sellerAgents = new AID[result.length];
						for (int i = 0; i < result.length; ++i) {
							sellerAgents[i] = result[i].getName();
							System.out.println(sellerAgents[i].getName());
						}
					} catch (FIPAException e) {
						e.printStackTrace();
					}
					
					myAgent.addBehaviour(new RequestPerformer());
				}
				
			});
		}
		else {
			System.out.println("No target book title specified");
			doDelete();
		}
	}

	@Override
	protected void takeDown() {
		System.out.println("Buyer-agent " + getAID().getName() + " terminating.");
	}
	
}